﻿/*----------------------------------------------------------------------------------------
*
*  Copyright 2019, Gao Hai Hui, <fromzeropoint@126.com>.  All rights reserved.
*  https://gitee.com/helloworldghh/xoskit.git
*  Use of this source code is governed by a MIT license
*  that can be found in the License file.
*
----------------------------------------------------------------------------------------*/
#ifndef __XOSKIT_XOS_CORE_XOS_STL_SRC_TOOLS_PTR_OBJ_H__
#define __XOSKIT_XOS_CORE_XOS_STL_SRC_TOOLS_PTR_OBJ_H__

#include <functional>
#include <algorithm>

namespace xos_stl
{

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    // base template class. c++ 17中被去掉了，自己改个名，加进来
    // 

    template <class Arg, class Result>      // 1个参数，一个返回值
    struct xos_unary_function {
        typedef Arg argument_type;
        typedef Result result_type;
    };

    template <class Arg1, class Arg2, class Result>
    struct xos_binary_function {
        typedef Arg1 first_argument_type;
        typedef Arg2 second_argument_type;
        typedef Result result_type;
    };

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    // binary object, user pointer arg
    // 

    template< class OBJ >
    struct binary_obj_p : public xos_binary_function< typename OBJ::first_argument_type, typename OBJ::second_argument_type, typename OBJ::result_type >
    {
        typedef typename OBJ::result_type result_type;
        typedef typename OBJ::first_argument_type first_argument_type;
        typedef typename OBJ::second_argument_type second_argument_type;

        explicit binary_obj_p( OBJ & obj ) :
            _obj( obj )
        {
        }

        result_type operator() ( const first_argument_type * pv1, const second_argument_type * pv2 ) const
        {
            return _obj( *pv1, *pv2 );
        }

        OBJ & _obj;
    };

    //
    // compose binary_obj_p
    // 

    template< class OBJ >
    inline binary_obj_p<OBJ> ptr_binary_obj_p( OBJ & _Obj )
    {
        return ( binary_obj_p< OBJ >( _Obj ) );
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    // unary object, user pointer arg
    // 

    template< class OBJ >
    struct unary_obj_p : public xos_unary_function< typename OBJ::argument_type, typename OBJ::result_type >
    {
        typedef typename OBJ::result_type result_type;
        typedef typename OBJ::argument_type argument_type;

        explicit unary_obj_p( OBJ & obj ) :
            _obj( obj )
        {
        }

        result_type operator() ( const argument_type * pv ) const
        {
            return _obj( *pv );
        }

        OBJ & _obj;
    };

    //
    // compose unary_obj_p
    // 

    template< class OBJ >
    inline unary_obj_p<OBJ> ptr_unary_obj_p( OBJ & _Obj )
    {
        return ( unary_obj_p< OBJ >( _Obj ) );
    }

} // xos_stl

#endif // __XOSKIT_XOS_CORE_XOS_STL_SRC_TOOLS_PTR_OBJ_H__
